<?php
/**
 * 微信授权控制器
 */

namespace app\home\controller;
use app\admin\controller\Base;
use think\Cache;
use think\Controller;

class WeixinAuth extends Controller
{
    protected $_appid;//公众号的唯一标识
    protected $appsecret;
    protected $redirect_uri;//回调地址
    /**
     * 应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），
     * snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
     */
    protected $scope;
    protected $state;//重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节
    protected $code;//code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。

    public $_error_number = 0;
    public $_error;
    protected $_refresh_token;
    protected $_access_token;
    protected $_openid;
    //初始化信息
    public function __construct($config=array()){
        $this->_appid = isset($config['appid']) ? trim($config['appid']) : 'wxfbd13d9aff8a913a';
        $this->appsecret = isset($config['appsecret']) ? trim($config['appsecret']) : '09d05919edad8d9cea72902bd91073de';
        $this->redirect_uri = isset($config['redirect_uri']) ? trim($config['redirect_uri']) : '';
        $this->scope = isset($config['scope']) ? trim($config['scope']) : 'snsapi_userinfo';
    }
    //获取网页授权code
    public function code(){
        $api_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?';
        $redirect_uri = urlencode("$this->redirect_uri");
        $code_url = $api_url."appid=".$this->_appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=".$this->scope."&state=STATE#wechat_redirect";
        $this->redirect($code_url);
    }

    /**
     * 获取访问token
     * @param bool $refresh 是否强制刷新
     * @return bool|mixed
     */
    public function getAuthAccessToken($refresh = false) {
        $code = request()->get('code','');
        $cache = Cache::get('auth_access_token');
        if ($cache && $refresh) {
            return array('access_token' => $cache, 'code' => $code);
        }
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->_appid."&secret=".$this->appsecret."&code=".$code."&grant_type=authorization_code";
        $res = $this->request($url);
        if ($res) {
            Cache::set('auth_access_token', $res['access_token']);
            Cache::set('auth_refresh_token', $res['refresh_token']);
            Cache::set('auth_openid', $res['openid']);
        } else {
            if ($this->_error_number == 42001) {
                return $this->refreshAccessToken();
            }elseif ($this->_error_number == 40163){
                return array('access_token' => $cache, 'code' => $code);
            }
        }
        return array('access_token' => $res['access_token'], 'code' => $code);
    }


    //https请求
    public function request($url, $data = null,$time_out=60,$out_level="s",$headers=array())
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_NOSIGNAL, 1);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        if($out_level=="s")
        {
            //超时以秒设置
            curl_setopt($curl, CURLOPT_TIMEOUT,$time_out);//设置超时时间
        }elseif ($out_level=="ms")
        {
            curl_setopt($curl, CURLOPT_TIMEOUT_MS,$time_out);  //超时毫秒，curl 7.16.2中被加入。从PHP 5.2.3起可使用
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        if($headers)
        {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//如果有header头 就发送header头信息
        }
        $res = curl_exec($curl);
        $res = json_decode($res, true);
        curl_close($curl);
        if (!empty($res)) {
            if (isset($res['errcode']) && $res['errcode']) {
                $this->_error_number = $res['errcode'];
                $this->_error = $res['errmsg'];
                return false;
            }
            return $res;
        }
    }

    /**
     * 刷新访问token
     * @return mixed
     */
    public function refreshAccessToken() {
        $code = request()->get('code','');
        $cache = Cache::get('auth_refresh_token');
        if ($cache) {
            $this->_refresh_token = $cache;
        }
        $url = " https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=".$this->_appid."&grant_type=refresh_token&refresh_token=".$this->_refresh_token;
        $res = $this->request($url);
        if ($res) {
            Cache::set('auth_access_token', $res['access_token']);
            Cache::set('auth_refresh_token', $res['refresh_token']);
            Cache::set('auth_openid', $res['openid']);
        }
        return array('access_token' => $res['access_token'], 'code' => $code);
    }

    /**
     * 获取用户信息
     * @param bool $refresh 是否强制刷新
     * @return bool|mixed
     */
    public function getUserInfo($refresh = false) {
        $this->_access_token = $this->getAuthAccessToken($refresh);
        $cache =  Cache::get('auth_openid');
        if ($cache) {
            $this->_openid = $cache;
        }

        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->_access_token['access_token']."&openid=".$this->_openid."&lang=zh_CN";
        $res = $this->request($url);

        if ($res) {
            return $res;
        }
        return false;
    }



}